#include"server.hpp"
#include"onlineuser.hpp"
#include<memory>
#include <signal.h>
#include<unordered_map>
#include <fstream>
using namespace std;
using namespace udpServer;
 const string dictText="./dict.txt";
 unordered_map<string,string> dict;
static void Usage(string proc)
{
    cerr<<"Usage: \n\t"<<proc<<" serverport"<<endl;
}

// static bool cutstring(const string&s,string*s1,string*s2,const string&sep)
// {
// auto iter=s.find(sep);
// if(iter==string::npos) return false;

// *s1=s.substr(0,iter);//把文件中按行区分开key

// *s2=s.substr(iter+sep.size());//区分开value
// return true;
// }


 static void initDict()
{
ifstream in(dictText,ios::binary);//从文件中读取数据，以二进制的方式打开文件
if(!in.is_open())
{
    cout<<"open file"<<dictText<<"error"<<endl;
    exit(OPEN_ERR);
}

string line,key,value;

while(getline(in,line))//从in中按行读取数据读到字符串line中
{
    cout<<line<<endl;
    // if(cutstring(line,&key,&value,":"))
    // {
    //     dict.insert(make_pair(key,value));
    // }
}

in.close();
cout<<"load dict success"<<endl;
}

void reload(int signal)
{
(void)signal;
initDict();//通过信号进行热加载字典初始化函数
}



static void debugstring()
{
    for(auto &dt:dict)
    {
        cout<<dt.first<<" # "<<dt.second<<endl;
    }
}
// //demo1小型翻译
void handlermessage(const int& sockfd,const string& ip,uint16_t port,string message)
{
    string resposemessage;
    auto iter=dict.find(message);
    if(iter==dict.end()) resposemessage="unknown";//字典内没找到对应内容
    else 
    resposemessage=iter->second;

//返回数据
struct sockaddr_in clientmg;
bzero(&clientmg,sizeof(clientmg));//清零结构体
clientmg.sin_family=AF_INET;
clientmg.sin_port=htons(port);
clientmg.sin_addr.s_addr=inet_addr(ip.c_str());
sendto(sockfd,resposemessage.c_str(),resposemessage.size(),0,(struct sockaddr*)&clientmg,sizeof(clientmg));
//sendto发回去給client端
}

//demo2--进行命令行解析
// void execCommand(const int& sockfd,const string& ip,uint16_t port,string cmd)
// {
// if(cmd.find("rm")!=string::npos||cmd.find("mv")!=string::npos||cmd.find("rmdir")!=string::npos)
// {
//      cerr<<ip<<"["<<port<<"] "<<"doing wrong things: "<<cmd<<endl;
//      return;
// }

// string respose;
// FILE*fp=popen(cmd.c_str(),"r");
// if(fp==nullptr) respose=cmd+"ecec failed";

// char line[1024];
// while(fgets(line,sizeof(line),fp))
// {
//     respose+=line;   
// }

// pclose(fp);

// // //返回数据
// struct sockaddr_in clientmg;
// bzero(&clientmg,sizeof(clientmg));//清零结构体
// clientmg.sin_family=AF_INET;
// clientmg.sin_port=htons(port);
// clientmg.sin_addr.s_addr=inet_addr(ip.c_str());
// sendto(sockfd,respose.c_str(),respose.size(),0,(struct sockaddr*)&clientmg,sizeof(clientmg));

// }

//demo3:聊天室：需要上线才能发消息和看到消息，并且登录的用户根据端口号区分
OnlineUser Onlineusers;
void routeMessage(const int& sockfd,const string& ip,uint16_t port,string message)
{
if(message=="Online"){Onlineusers.AddOnlineUser(ip,port);}
if(message=="Offline"){Onlineusers.DeleteOnlineUser(ip,port);}
if(Onlineusers.isOnline(ip,port))
{
    Onlineusers.broadcastMessage(sockfd,ip,port,message);
}else
{
    struct sockaddr_in clientmg;
bzero(&clientmg,sizeof(clientmg));//清零结构体
clientmg.sin_family=AF_INET;
clientmg.sin_port=htons(port);
clientmg.sin_addr.s_addr=inet_addr(ip.c_str());
string respose="你还没上线呢,请先上线,输入Online: ";
sendto(sockfd,respose.c_str(),respose.size(),0,(struct sockaddr*)&clientmg,sizeof(clientmg));
}
}

int main(int argc,char* argv[])
{
if(argc!=2)
{
 Usage(argv[0]);
 exit(USAGE_ERR);
}

uint16_t port=atoi(argv[1]);//atoi作用：把port的str类型转化成int类型。而uin16_t本质类型是int

initDict();
 debugstring();
unique_ptr<udpserver> uspr(new udpserver(handlermessage,port));
//unique_ptr<udpserver> uspr(new udpserver(execCommand,port));
//unique_ptr<udpserver> uspr(new udpserver(routeMessage,port));
// uspr->initudpserver();//初始化服务端
 uspr->start();//启动服务端
return 0;
}
